﻿
using System;
using FlexiCommerce.Components;

namespace FlexiCommerce.Persistence
{
	/// <summary>
	/// Represents a class responsible for (database) persistence of content 
	/// items and details therof.
	/// </summary>
	public interface IPersister: IDisposable
	{
        /// <summary>Gets the repository implementation used by this persister. Please note that using the using the repository circumvent events exposed by the persister and is not run in a transaction. Do net expect the behaviour to be exactly the same.</summary>
        IRepository<int, GenericPersistenceItem> Repository { get; }

		/// <summary>Loads the content item with the supplied id or returns null if no items matches that identifier.</summary>
		/// <param name="id">The identifier of the item to retrieve.</param>
		/// <returns>The matching item or null if no item was found.</returns>
		GenericPersistenceItem Get(int id);

		/// <summary>Loads the content item with the supplied id or returns null if no items matches that identifier.</summary>
		/// <typeparam name="T">The type of item to load.</typeparam>
		/// <param name="id">The identifier of the item to retrieve.</param>
		/// <returns>The matching item or null if no item was found.</returns>
		T Get<T>(int id) where T : PersistenceItem;
		
		/// <summary>Saves an item to persistence medium.</summary>
		/// <param name="unsavedItem">The item to save.</param>
		/// <remarks>When using <see cref="FlexiCommerce.Persistence.NH.ContentPersister"/> changes on existing items are tracked and automatically persisted.</remarks>
		void Save(PersistenceItem unsavedItem);

		/// <summary>Deletes an item including child items, any associations towards it (<see cref="FlexiCommerce.Details.LinkDetail"/>) and previous versions.</summary>
		/// <param name="itemNoMore">The item to delete.</param>
        void Delete(PersistenceItem itemNoMore);

		/// <summary>Moves an item and it's chlid items to a place below the new destination.</summary>
		/// <param name="source">The item to move.</param>
		/// <param name="destination">The below which the moved item will be placed.</param>
        void Move(HierarchicalPersistenceItem source, HierarchicalPersistenceItem destination);

		/// <summary>Persist changes.</summary>
		void Flush();

		/// <summary>Occurs before an item is saved</summary>
		event EventHandler<CancellableItemEventArgs> ItemSaving;
		/// <summary>Occurs when an item has been saved</summary>
		event EventHandler<ItemEventArgs> ItemSaved;
		/// <summary>Occurs before an item is deleted</summary>
		event EventHandler<CancellableItemEventArgs> ItemDeleting;
		/// <summary>Occurs when an item has been deleted</summary>
		event EventHandler<ItemEventArgs> ItemDeleted;
		/// <summary>Occurs before an item is moved</summary>
		event EventHandler<CancellableDestinationEventArgs> ItemMoving;
		/// <summary>Occurs when an item has been moved</summary>
		event EventHandler<DestinationEventArgs> ItemMoved;
		/// <summary>Occurs before an item is copied</summary>
		event EventHandler<CancellableDestinationEventArgs> ItemCopying;
		/// <summary>Occurs when an item has been copied</summary>
		event EventHandler<DestinationEventArgs> ItemCopied;
		/// <summary>Occurs when an item is loaded</summary>
		event EventHandler<ItemEventArgs> ItemLoaded;

        System.Web.DynamicData.ModelProviders.DataModelProvider DataModel { get; }
        System.ComponentModel.TypeDescriptionProvider TypeDescriptor(Type type);
        Components.Image SaveImage(System.IO.Stream imageStream);
        Components.Configuration GetConfiguration();
	}
}
